#! /usr/bin/env python3
# -*- coding:UTF-8 -*-
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import cgi
import base64
import time
import random
import sys, os

import pdb

# host = ('localhost', 6666)
host = ('',6666)
# import pyyolo
sys.path.append('/root/darknet/python')
import numpy as np
import sys
import cv2
import re
import os

# 权重文件路径
BASE_PATH = os.getcwd()
pic_save_path = os.path.join(BASE_PATH, 'own/pic_save')

import darknet as dn
dn.set_gpu(0)
# 模型加载
print('Vehicle Type loading...')
net_type = dn.load_net(os.path.join(BASE_PATH, 'own/struct/yolov3.cfg').encode('utf-8'), os.path.join(BASE_PATH, 'own/weights/yolov3-type.weights').encode('utf-8'), 0)
meta_type = dn.load_meta(os.path.join(BASE_PATH, 'own/struct/voc_type.data').encode('utf-8'))
print('Vehicle Length loading...')
net_length = dn.load_net(os.path.join(BASE_PATH, 'own/struct/yolov3-voc.cfg').encode('utf-8'), os.path.join(BASE_PATH, 'own/weights/yolov3-length.weights').encode('utf-8'), 0)
meta_length = dn.load_meta(os.path.join(BASE_PATH, 'own/struct/voc_length.data').encode('utf-8'))
print('Vehicle Type special loading')
net_type_special = dn.load_net(os.path.join(BASE_PATH, 'own/struct/yolov3.cfg').encode('utf-8'), os.path.join(BASE_PATH, 'own/weights/yolov3-type-special.weights').encode('utf-8'), 0)
meta_type_special = dn.load_meta(os.path.join(BASE_PATH, 'own/struct/voc_type.data').encode('utf-8'))

def random_num():
    a = random.randint(200, 300)  # top
    b = random.randint(200, 300)  # left
    c = random.randint(80, 150)  # bottom
    d = random.randint(80, 150)  # right
    prob = random.uniform(0.9, 1.0)
    return a, b, c, d, prob
    pass


def time_name(path):
    if not os.path.exists(path):
        os.mkdir(path)
    nowtime = time.localtime(time.time())
    name_time = str(nowtime.tm_year) + str(nowtime.tm_mon) + str(nowtime.tm_mday) + str(nowtime.tm_hour) \
                + str(nowtime.tm_min) + str(nowtime.tm_sec)
    name_time += '.jpg'
    return os.path.join(path, name_time)


def save_pict(picture, img):
    try:
        file = open(picture, 'wb')
        file.write(img)
        file.close()
    except:
        print('save pic error')


def _base64_decode(data):
    try:
        missing_padding = 4 - len(data) % 4
        if missing_padding:
            data += '=' * missing_padding
        data = re.sub('%3D', '=', data)
        return base64.urlsafe_b64decode(data)
    except:
        print('decode error')


def handle_pic(img_path, net_type, meta_type, net_length, meta_length):
    res_type = dn.detect(net_type, meta_type, img_path.encode('utf-8'))

    res_length = dn.detect(net_length, meta_length, img_path.encode('utf-8'))

    return res_type, res_length


def return_data(outputs, _flag = True):
    if len(outputs) == 0 and _flag:
        data = dict()
    elif len(outputs) == 0 and _flag == False:
        top, left, bottom, right, prob = random_num()
        data = {'class': '02', 'x': str(top), 'y': str(left), 'w': str(bottom), 'h': str(right),
                'prob': str(prob)}
    else:
        data = dict()
       
        data['class'] = outputs[0][0].decode('utf-8')
        data['prob'] = outputs[0][1]
        data['x'] = outputs[0][2][0]
        data['y'] = outputs[0][2][1]
        data['w'] = outputs[0][2][2]
        data['h'] = outputs[0][2][3]
    return data

def handle_chexing_special(img_path, net_type_special, meta_type_special):
    r_type_special = dn.detect(net_type_special, meta_type_special, img_path.encode('utf-8'))
    return return_data(r_type_special)


class TodoHandler(BaseHTTPRequestHandler):
    """A simple TODO server

    which can display and manage todos for you.
    """



    def do_GET(self):
        self.send_error(415, 'Only post is supported')

    def do_POST(self):
        """Add a new todo

        Only json data is supported, otherwise send a 415 response back.
        Append new todo to class variable, and it will be displayed
        in following get request
        """
        ctype, pdict = cgi.parse_header(self.headers['content-type'])


        if ctype == 'application/x-www-form-urlencoded':
            # 分析数据，然后解码保存图片
            length = int(self.headers['content-length'])

            img_base64 = self.rfile.read(length).decode().split('=')[1]
            img = _base64_decode(img_base64)

            name_time = time_name(pic_save_path)
            save_pict(name_time, img)

            # 返回两个值，每个值是一个list，list内每个被检测到的目标为一个tuple
            outputs_type, outputs_length = handle_pic(name_time, net_type, meta_type,net_length, meta_length)

            """判别图片"""
            data = {}
            data['type'] = return_data(outputs_type)
            data['length'] = return_data(outputs_length, _flag=False)
            if (not data['type']) or float(data['type']['prob']) < 0.85:

                data['type'] = handle_chexing_special(name_time, net_chexing_special, meta_chexing_special)

            os.remove(name_time)

            self.send_response(200)
            self.send_header('Content-type', 'application/x-www-form-urlencoded')
            self.end_headers()
            self.wfile.write(json.dumps(data).encode())

        else:
            self.send_error(415, "Only json data is supported.")

if __name__ == '__main__':
    
    server = HTTPServer(host, TodoHandler)
    print("Starting server, listen at: %s:%s" % host)
    server.serve_forever()

